﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Web.Hosting;
using CI.Mesopotamia;
using CI.Mesopotamia.WebService;
using CI.Organism;
using CI.WebService;

namespace MesopotamiaDCProxy
{
    public class Inbound : IInbound
    {
        #region Table Adapters, Views, Query's
        private readonly GridDBTableAdapters.UsersTableAdapter _uta = new GridDBTableAdapters.UsersTableAdapter();
        private readonly GridDBTableAdapters.QueriesTableAdapter _qta = new GridDBTableAdapters.QueriesTableAdapter();
        #endregion

        /// <summary>
        /// Scenario helper class
        /// </summary>
        private readonly DBHelper _dbHelper = new DBHelper();

        /// <summary>
        /// ctor
        /// </summary>
        public Inbound()
        {
            // set launch from to wcf
            CI.Globals.LaunchedFrom = CI.LaunchType.WCFService;

            // wire up the test excpetion handler
            AppDomain.CurrentDomain.UnhandledException += ExceptionHandler;
        }

        /// <summary>
        /// Exception catcher across threads 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private static void ExceptionHandler(Object sender, UnhandledExceptionEventArgs args)
        {
            ExceptionLogger((Exception)args.ExceptionObject);
        }

        /// <summary>
        /// Exception Logger
        /// </summary>
        /// <param name="e"></param>
        private static void ExceptionLogger(Exception e)
        {
            WebLogger.LogWarn("Caught : " + e.Message);
            WebLogger.LogWarn("Stack : " + e.StackTrace);
            WebLogger.LogWarn("Source :  " + e.Source);
            WebLogger.LogWarn("Target Site : " + e.TargetSite);

            // check inner exception
            if (e.InnerException != null)
            {
                if (!(string.IsNullOrEmpty(e.InnerException.Message)))
                {
                    WebLogger.LogWarn("Inner Exception Message : " + e.InnerException.Message);
                }

                if (!(string.IsNullOrEmpty(e.InnerException.StackTrace)))
                {
                    WebLogger.LogWarn("Inner Exception Stack : " + e.InnerException.StackTrace);
                }
            }
        }

        /// <summary>
        /// upload the logs
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="logName"></param>
        public void UploadLogs(byte[] bytes, string logName)
        {
            UploadLogsForUser(bytes, logName, 0);
        }

        /// <summary>
        /// upload the logs
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="logName"></param>
        /// <param name="userId"></param>
        public void UploadLogsForUser(byte[] bytes, string logName, int userId)
        {
            System.IO.File.WriteAllBytes(HostingEnvironment.ApplicationPhysicalPath + @"/logs/" + logName + Guid.NewGuid() + ".log", bytes);
        }

        public Organism LoadOrganism(Guid organismGuid, int userId)
        {
            return _dbHelper.LoadOrganisms(new ScenarioLocalXML(), 0, false, 1, new List<Guid> { organismGuid }).Cast<Organism>().FirstOrDefault();
        }

        /// <summary>
        /// increment counter, test method
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        public int Increment(int number)
        {
            return ++number;
        }

        /// <summary>
        /// Diagnostic DB check just get the number of users
        /// </summary>
        /// <returns></returns>
        public int DiagGetUsersDbCount(int userId)
        {
            return _uta.GetData().Count;
        }

        /// <summary>
        /// Get a user ID, may be new, will get old one if it exists
        /// </summary>
        /// <param name="machineName">machine name</param>
        /// <param name="hostVersion">host version</param>
        /// <returns></returns>
        public int GetNewUserId(string machineName, string hostVersion)
        {
            return int.Parse(_qta.usp_getUserID(machineName, hostVersion).ToString());
        }

        /// <summary>
        /// Get the list of scenarios
        /// </summary>
        /// <returns></returns>
        public string[] GetScenarioList(string hostVersion, int userId)
        {
            return _dbHelper.GetScenarioList(hostVersion).ToArray();
        }

        public ScenarioOrganismCollection GetScenarioOrganisms(string scenarioName, int startIndex, int endIndex)
        {
            return _dbHelper.GetScenarioOrganisms(scenarioName, startIndex, endIndex);
        }

        /// <summary>
        /// Delete a scenario by name
        /// </summary>
        /// <param name="scenarioName"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public bool DeleteScenario(string scenarioName, int userId)
        {
            return _dbHelper.DeleteScenario(scenarioName);
        }

        /// <summary>
        /// Get the preferred scenario for the host version
        /// </summary>
        /// <param name="hostVersion"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public string GetPreferredScenario(string hostVersion, int userId)
        {
            // todo : this currently just returns the last scenario added, make it dynamic based on host version
            //List<string> _results = _dbHelper.GetScenarioList(hostVersion);
            //return _results[_results.Count - 1];

            //return "Survival of the Fattest";
            return "Clean my house";
            //return "Do Not Use";
        }

        /// <summary>
        /// save the scenario passed to it
        /// </summary>
        /// <param name="scenario"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public int SaveScenario(Scenario scenario, int userId)
        {
            return _dbHelper.SaveScenario(scenario, userId);
        }

        /// <summary>
        /// Get a scenario based on the name passed to it
        /// </summary>
        /// <param name="scenarioName"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public Scenario LoadScenario(string scenarioName, int userId)
        {
            return _dbHelper.LoadScenario(scenarioName);
        }

        /// <summary>
        /// Load the dal
        /// </summary>
        /// <param name="scenarioName">scenario to load it from</param>
        /// <param name="userId"></param>
        /// <param name="organismCount"></param>
        /// <param name="organismsToLoad"></param>
        /// <returns>list of organisms</returns>
        public CI.DAL.DALList LoadDal(string scenarioName, int userId, int organismCount, Guid[] organismsToLoad)
        {
            return _dbHelper.LoadDAL(scenarioName, organismCount, organismsToLoad);
        }

        /// <summary>
        /// save the scenario dal
        /// </summary>
        /// <param name="scenarioName">scenario name to save it to</param>
        /// <param name="organisms">list of organisms</param>
        /// <param name="userId"></param>
        public int SaveDal(string scenarioName, CI.DAL.DALList organisms, int userId)
        {
            return _dbHelper.SaveDAL(scenarioName, organisms, userId);
        }

    }

    /// <summary>
    /// Fixes issue hosting on discountasp.net
    /// </summary>
    public class MyServiceHostFactory : ServiceHostFactory
    {

        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            // webservice
            Uri webServiceAddress;

            // Specify the exact URL of your web service            
#if PUBLISH
            webServiceAddress = new Uri("http://www.mesopotamiaexperiment.com/inbound.svc");
#else
            webServiceAddress = new Uri("http://localhost/MesopotamiaDCProxy/inbound.svc");
#endif

            var webServiceHost = new ServiceHost(serviceType, webServiceAddress);

            return webServiceHost;
        }

    }

}
